﻿using System;
using System.Runtime.Serialization;

namespace OpenComposite.HumanActivity.Contracts.Participants
{
	/// <summary>
	/// A participant for human activities.
	/// </summary>
	[DataContract(Name = "Participant", Namespace = "http://www.theopencomposite.com/humanactivities")]
	public class ParticipantItem : IEquatable<ParticipantItem>, IParticipant
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="Participant"/> class for an included participant.
		/// </summary>
		/// <param name="type">The type of the participant.</param>
		/// <param name="id">The id of the participant.</param>
		public ParticipantItem(ParticipantType type, int id)
		{
			this.ParticipantType = type;
			this.ID = id;
			this.ParticipationType = ParticipationType.IncludedParticipant;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="Participant"/> class.
		/// </summary>
		/// <param name="type">The type.</param>
		/// <param name="id">The id.</param>
		/// <param name="participationType">Type of the participation.</param>
		public ParticipantItem(ParticipantType type, int id, ParticipationType participationType)
		{
			this.ParticipantType = type;
			this.ID = id;
			this.ParticipationType = participationType;
		}

		/// <summary>
		/// Gets or sets the type of the participant.
		/// </summary>
		/// <value>The type of the participant.</value>
		[DataMember]
		public ParticipantType ParticipantType { get; private set; }
		/// <summary>
		/// Gets or sets the participation type of the participant.
		/// </summary>
		/// <value>The type of the participation.</value>
		[DataMember]
		public ParticipationType ParticipationType { get; set; }
		/// <summary>
		/// Gets or sets the ID of the participant.
		/// </summary>
		/// <value>The ID.</value>
		[DataMember]
		public int ID { get; private set; }
		/// <summary>
		/// Gets or sets displayable text for the participant.
		/// </summary>
		/// <value>The display text.</value>
		[DataMember(IsRequired = false)]
		public string Display { get; set; }

		/// <summary>
		/// Gets or sets a value indicating whether this participant is included. or excluded
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this participant is included; otherwise, <c>false</c>.
		/// </value>
		public bool IsIncluded
		{
			get
			{
				return ( this.ParticipationType == ParticipationType.IncludedParticipant ||
						this.ParticipationType == ParticipationType.IncludedPastDueParticipant ||
						this.ParticipationType == ParticipationType.IncludedReaderParticipant );
			}
			set
			{
				if ( this.ParticipationType == ParticipationType.ExcludedPastDueParticipant ||
					 this.ParticipationType == ParticipationType.IncludedPastDueParticipant ) {
					this.ParticipationType = value ?
						ParticipationType.IncludedPastDueParticipant :
						ParticipationType.ExcludedPastDueParticipant;
				} else if ( this.ParticipationType == ParticipationType.ExcludedReaderParticipant ||
							this.ParticipationType == ParticipationType.IncludedReaderParticipant ) {
					this.ParticipationType = value ?
						ParticipationType.IncludedReaderParticipant :
						ParticipationType.ExcludedReaderParticipant;
				} else {
					this.ParticipationType = value ?
						ParticipationType.IncludedParticipant : ParticipationType.ExcludedParticipant;
				}
			}
		}
		/// <summary>
		/// Gets or sets a value indicating whether this participant is a readonly participant.
		/// </summary>
		/// <value><c>true</c> if this participant is a readonly participant; otherwise, <c>false</c>.</value>
		public bool IsReader
		{
			get
			{
				return ( this.ParticipationType == ParticipationType.ExcludedReaderParticipant ||
						this.ParticipationType == ParticipationType.IncludedReaderParticipant );
			}
			set
			{
				if ( value ) { // is reader participant
					if ( this.ParticipationType == ParticipationType.ExcludedParticipant ||
						 this.ParticipationType == ParticipationType.ExcludedPastDueParticipant ||
						 this.ParticipationType == ParticipationType.ExcludedReaderParticipant ) {
						this.ParticipationType = ParticipationType.ExcludedReaderParticipant;
					} else {
						this.ParticipationType = ParticipationType.IncludedReaderParticipant;
					}
				} else { // is NOT reader participant
					if ( this.ParticipationType == ParticipationType.IncludedReaderParticipant ) {
						this.ParticipationType = ParticipationType.IncludedParticipant;
					} else if ( this.ParticipationType == ParticipationType.ExcludedReaderParticipant ) {
						this.ParticipationType = ParticipationType.ExcludedParticipant;
					}
				}
			}
		}
		/// <summary>
		/// Gets or sets a value indicating whether this participant is a past due participant.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this participant is a past due participant; otherwise, <c>false</c>.
		/// </value>
		public bool IsPastDue
		{
			get
			{
				return ( this.ParticipationType == ParticipationType.ExcludedPastDueParticipant ||
						this.ParticipationType == ParticipationType.IncludedPastDueParticipant );
			}
			set
			{
				if ( value ) { // is past due participant
					if ( this.ParticipationType == ParticipationType.ExcludedParticipant ||
						 this.ParticipationType == ParticipationType.ExcludedPastDueParticipant ||
						 this.ParticipationType == ParticipationType.ExcludedReaderParticipant ) {
						this.ParticipationType = ParticipationType.ExcludedPastDueParticipant;
					} else {
						this.ParticipationType = ParticipationType.IncludedPastDueParticipant;
					}
				} else { // is NOT past due participant
					if ( this.ParticipationType == ParticipationType.IncludedPastDueParticipant ) {
						this.ParticipationType = ParticipationType.IncludedParticipant;
					} else if ( this.ParticipationType == ParticipationType.ExcludedPastDueParticipant ) {
						this.ParticipationType = ParticipationType.ExcludedParticipant;
					}
				}
			}
		}

		public override bool Equals(object obj)
		{
			ParticipantItem other = obj as ParticipantItem;
			return ( other != null &&
					other.ID == this.ID &&
					other.ParticipantType == this.ParticipantType &&
					other.ParticipationType == this.ParticipationType );
		}
		public override int GetHashCode()
		{
			return this.ID ^ (int)this.ParticipantType ^ (int)this.ParticipationType;
		}
		public override string ToString()
		{
			return string.Format("{0}:{1}:{2}", this.ParticipationType, this.ParticipantType, this.ID);
		}

		#region IEquatable<Participant> Members

		public bool Equals(ParticipantItem other)
		{
			return ( other != null &&
					other.ID == this.ID &&
					other.ParticipantType == this.ParticipantType &&
					other.ParticipationType == this.ParticipationType );
		}

		#endregion

		#region IEquatable<IParticipant> Members

		public bool Equals(IParticipant other)
		{
			throw new NotImplementedException();
		}

		#endregion
	}
}
